package com.learn.spring.test;

import com.learn.spring.User;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.support.GenericApplicationContext;

public class Case7 {
    /**
     * Spring5 框架新功能
     * 1、整个 Spring5 框架的代码基于 Java8，运行时兼容 JDK9，许多不建议使用的类和方法在代码库中删除
     * 2、Spring 5.0框架自带了通用的日志封装
     *  (1) Spring5 已经移除 Log4jConfigListener，官方建议使用Log4j2
     *  (2) Spring5 框架整合 Log4j2
     *  第一步引入jar包。
     *  log4j2 在 2021年12月份爆发远程代码执行漏洞，原理是基于 JNDI 的网络执行注入攻击。与SQL注入一样，用户可在输入框中拼接 JNDI 的网络执行协议。
     *  并在其他云端服务器上搭建一个远程过程服务器，当 log4J2 识别到 JNDI 协议时，为依据协议去调用云端服务的方法代码。且这个方法代码执行是在本地而非云端服务器。
     *  这样黑客可利用事先实现好的代码逻辑在目标服务器上运行任何代码。此 bug 在 12月内连打3个补丁，从 2.15.0 版本以后的简单修复到 2.17.0 版本目前看没有问题的版本修复，
     *  这个bug版本之前可通过：
     *      1) 设置jvm参数 “-Dlog4j2.formatMsgNoLookups=true”
     *      2) 设置 “log4j2.formatMsgNoLookups=True”
     *      3) 系统环境变量 “FORMAT_MESSAGES_PATTERN_DISABLE_LOOKUPS” 设置为 “true”
     *      4) 关闭对应应用的网络外连，禁止主动外连
     *  等方式来临时修复。
     *  log4j-core-2.17.x.jar => log4j 的核心库
     *  log4j-api-2.17.x.jar => log4j 对外暴露的操作API接口，依赖于核心库 core
     *  log4j-slf4j-impl-2.17.x.jar => log4j 提供的实现了 slf4j-api 接口规范的操作集，它是以 slf4j 的标准来封装了 log4j-api。
     *  slf4j-api-1.7.32.jar => simple logging facade for java 直译：java的简单日志外观，作用是提供了一套标准的简单操作不同日志框架的API。具体实现由各厂商实现。
     *
     *  第二步创建 log4j2.xml,这是个固定文件，固定文件名。内容固定有标准规范。
     */
    private static final Logger log = LoggerFactory.getLogger(Case7.class);
    @Test
    public void test1() {
       log.info("hello log4j2");
       log.warn("hello log4j2");
    }

    /**
     * 3、Spring5 框架核心容器支持 @Nullable 注解
     *  (1) @Nullable 注解可以使用在方法上面，属性上面，参数上面，表示方法返回可以为空，属性值可以为空，参数值可以为空
     * 4、Spring5 核心容器支持函数式风格 GenericApplicationContext
     */
    // 函数式风格注册Bean
    @Test
    public void test2() {
        // 1. 创建 GenericApplicationContext
        GenericApplicationContext context = new GenericApplicationContext();
        // 2. 清空一下容器
        context.refresh();
        // 3.调用 context 方法调用对象
        context.registerBean("user", User.class, () -> new User());
//        context.registerBean(User.class, () -> new User());
        // 4.获取注册对象
        User user= (User) context.getBean("user"); // 获取不到对象，不能按照配置或注解的习惯方式，使用类名首字母小写来获取对象。需要全名
//        User user= (User) context.getBean("com.learn.spring.User");

        System.out.println(user);
    }

}
